import React, { useEffect, useState, useMemo, useCallback, memo, useRef } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { novelsApi } from '../services/api';
import { progressOperations, novelOperations } from '../db/operations';
import db from '../db/database';
import { FiClock, FiBook, FiBookOpen, FiX, FiChevronRight, FiSettings, FiGrid, FiList, FiStar, FiColumns, FiMenu, FiChevronLeft, FiSearch, FiCornerDownLeft, FiSun, FiMoon, FiDownload, FiWifiOff, FiTrash2, FiDatabase, FiTool, FiLoader, FiRefreshCw, FiWifi, FiCheck } from 'react-icons/fi';

// 格式化字数显示
const formatWordCount = (count) => {
  if (count >= 10000) {
    return `${(count / 10000).toFixed(1)}万字`;
  }
  return `${count}字`;
};

// 格式化日期显示
const formatDate = (dateString) => {
  if (!dateString) return '未知';
  
  const date = new Date(dateString);
  const now = new Date();
  const isToday = date.toDateString() === now.toDateString();
  const isYesterday = new Date(now - 86400000).toDateString() === date.toDateString();
  
  if (isToday) {
    return `今天 ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
  } else if (isYesterday) {
    return `昨天 ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
  } else {
    return `${date.getMonth() + 1}月${date.getDate()}日 ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
  }
};

// ThemeContext
const ThemeContext = React.createContext({
  isDarkMode: false,
  toggleTheme: () => {}
});

function ThemeProvider({ children }) {
  const [isDarkMode, setIsDarkMode] = useState(() => {
    // 检查用户偏好的主题
    const savedTheme = localStorage.getItem('theme');
    if (savedTheme) {
      return savedTheme === 'dark';
    }
    // 检查系统偏好
    return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
  });
  
  // 切换主题
  const toggleTheme = useCallback(() => {
    setIsDarkMode(prev => {
      const newMode = !prev;
      localStorage.setItem('theme', newMode ? 'dark' : 'light');
      return newMode;
    });
  }, []);
  
  // 设置文档根元素上的类
  useEffect(() => {
    if (isDarkMode) {
      document.documentElement.classList.add('dark');
    } else {
      document.documentElement.classList.remove('dark');
    }
  }, [isDarkMode]);
  
  // 监听系统主题变化
  useEffect(() => {
    if (!window.matchMedia) return;
    
    const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
    const handleChange = (e) => {
      // 只有用户没有明确设置主题时，才跟随系统变化
      if (!localStorage.getItem('theme')) {
        setIsDarkMode(e.matches);
      }
    };
    
    mediaQuery.addEventListener('change', handleChange);
    return () => mediaQuery.removeEventListener('change', handleChange);
  }, []);
  
  const value = {
    isDarkMode,
    toggleTheme
  };
  
  return (
    <ThemeContext.Provider value={value}>
      {children}
    </ThemeContext.Provider>
  );
}

function useTheme() {
  return React.useContext(ThemeContext);
}

// 阅读记录弹窗组件
const ReadingHistoryPopup = ({ isOpen, onClose, recentReads, recentReadsNovels, onRead }) => {
  if (!isOpen) return null;
  
  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50">
      <div className="bg-white rounded-lg shadow-xl w-full max-w-lg mx-4 overflow-hidden">
        <div className="p-4 bg-blue-50 flex justify-between items-center border-b">
          <h3 className="text-xl font-semibold flex items-center">
            <FiBookOpen className="mr-2 text-blue-500" /> 继续阅读
          </h3>
          <button 
            onClick={onClose}
            className="text-gray-500 hover:text-gray-700 p-1 rounded-full hover:bg-gray-100"
          >
            <FiX size={24} />
          </button>
        </div>
        
        <div className="max-h-96 overflow-y-auto">
          {recentReads.length === 0 ? (
            <div className="p-4 text-center text-gray-500 text-base">
              暂无阅读记录
            </div>
          ) : (
            recentReads.map(item => {
              const novel = recentReadsNovels[item.novelId];
              if (!novel) return null;
              
              return (
                <div 
                  key={item.novelId}
                  className="flex items-center p-4 border-b hover:bg-gray-50 cursor-pointer transition-colors"
                  onClick={() => {
                    onRead(novel, item);
                    onClose();
                  }}
                >
                  <div className="p-3 bg-blue-100 rounded-full mr-4 text-blue-500">
                    <FiBookOpen size={24} />
                  </div>
                  <div className="flex-1">
                    <h4 className="font-medium text-gray-900 text-base sm:text-base">{novel.name}</h4>
                    <div className="mt-1 flex flex-col sm:flex-row sm:items-center text-sm text-gray-500">
                      <span className="flex items-center mr-3">
                        <FiClock className="mr-1" />
                        {formatDate(item.timestamp)}
                      </span>
                      {item.totalProgress > 0 && (
                        <div className="mt-1 sm:mt-0 flex items-center">
                          <span className="bg-green-100 text-green-800 px-2 py-0.5 rounded">
                            已读 {item.totalProgress}%
                          </span>
                        </div>
                      )}
                    </div>
                    {item.totalProgress > 0 && (
                      <div className="mt-2 w-full bg-gray-200 rounded-full h-2">
                        <div 
                          className="bg-blue-500 h-2 rounded-full" 
                          style={{ width: `${item.totalProgress}%` }}
                        ></div>
                      </div>
                    )}
                  </div>
                  <FiChevronRight className="text-gray-400 ml-2" size={20} />
                </div>
              );
            })
          )}
        </div>
        
        <div className="p-4 bg-gray-50 flex justify-center">
          <button 
            className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 text-base"
            onClick={onClose}
          >
            关闭
          </button>
        </div>
      </div>
    </div>
  );
};

// 最近阅读项组件
const RecentReadItem = memo(({ item, novel, onRead }) => {
  if (!novel) return null;
  
  return (
    <div 
      className="flex items-center p-3 border-b hover:bg-gray-50 cursor-pointer"
      onClick={() => onRead(novel, item)}
    >
      <div className="p-2 bg-blue-100 rounded-full mr-3">
        <FiBookOpen className="text-blue-500" size={18} />
      </div>
      <div className="flex-1">
        <h3 className="font-medium text-gray-900 truncate text-sm sm:text-base">{novel.name}</h3>
        <div className="flex items-center text-xs sm:text-sm text-gray-500">
          <span className="flex items-center mr-3">
            <FiClock className="mr-1" />
            {formatDate(item.timestamp)}
          </span>
          {item.totalProgress > 0 && (
            <span className="bg-green-100 text-green-800 px-2 py-0.5 rounded">
              已读 {item.totalProgress}%
            </span>
          )}
        </div>
      </div>
    </div>
  );
});

// 单个小说卡片组件，使用memo减少重渲染
const NovelCard = memo(({ novel, isFavorite, readingProgress, onToggleFavorite, onRead }) => {
  const { isDarkMode } = useTheme();
  
  return (
    <div 
      className={`${isDarkMode ? 'bg-gray-800 border-gray-700' : 'bg-white border-gray-200'} 
      border p-2 sm:p-4 rounded-lg shadow-sm hover:shadow-md transition-all duration-300 relative overflow-hidden group cursor-pointer transform hover:-translate-y-1`}
      onClick={() => onRead(novel, readingProgress)}
    >
      {/* 背景装饰元素 */}
      <div className={`absolute top-0 right-0 w-24 h-24 ${isDarkMode ? 'bg-gray-700' : 'bg-blue-50'} rounded-full -mr-12 -mt-12 z-0 group-hover:${isDarkMode ? 'bg-gray-600' : 'bg-blue-100'} transition-colors duration-300`}></div>
      
      {/* 类别标签 */}
      {novel.wordCount > 500000 ? (
        <div className="absolute top-2 sm:top-3 left-0 bg-indigo-500 text-white text-xs sm:text-sm font-medium py-0.5 px-1 sm:px-2 rounded-r shadow-sm">
          长篇
        </div>
      ) : novel.wordCount > 100000 ? (
        <div className="absolute top-2 sm:top-3 left-0 bg-green-500 text-white text-xs sm:text-sm font-medium py-0.5 px-1 sm:px-2 rounded-r shadow-sm">
          中篇
        </div>
      ) : (
        <div className="absolute top-2 sm:top-3 left-0 bg-blue-500 text-white text-xs sm:text-sm font-medium py-0.5 px-1 sm:px-2 rounded-r shadow-sm">
          短篇
        </div>
      )}
      
      {/* 缓存状态标签 */}
      {novel.cached && (
        <div className="absolute top-2 sm:top-3 right-8 sm:right-10 text-green-500" title="已缓存，可离线阅读">
          <FiDownload className="drop-shadow-sm" />
        </div>
      )}
      
      {/* 点击阅读提示 - 仅在悬停时显示 */}
      <div className="absolute inset-0 bg-black bg-opacity-60 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300 rounded-lg z-20">
        <div className="text-white flex flex-col items-center">
          <FiBookOpen size={24} className="mb-1 sm:mb-2" />
          <span className="font-medium text-sm sm:text-base">{readingProgress ? '继续阅读' : '开始阅读'}</span>
        </div>
      </div>
      
      {/* 收藏星标 */}
      <button 
        className="absolute top-1 right-1 sm:top-3 sm:right-3 text-xl sm:text-2xl z-10 transition-transform duration-300 hover:scale-125"
        onClick={(e) => {
          e.stopPropagation();
          onToggleFavorite(novel.id);
        }}
      >
        {isFavorite ? 
          <span className="text-yellow-500 drop-shadow-sm animate-pulse text-xl sm:text-3xl">★</span> : 
          <span className={`${isDarkMode ? 'text-gray-500 hover:text-yellow-400' : 'text-gray-300 hover:text-yellow-400'} text-xl sm:text-3xl`}>☆</span>
        }
      </button>
      
      <div className="relative z-10">
        <h2 className={`text-base sm:text-xl font-semibold pr-6 sm:pr-8 truncate mt-1 ${isDarkMode ? 'text-gray-100' : 'text-gray-800'}`}>{novel.name}</h2>
        
        {/* 小说简短描述 - 在移动设备上隐藏 */}
        <p className={`mt-1 text-xs sm:text-sm ${isDarkMode ? 'text-gray-400' : 'text-gray-500'} h-8 overflow-hidden hidden sm:block`}>
          {novel.description || `《${novel.name}》是一部${novel.wordCount > 500000 ? '长篇' : novel.wordCount > 100000 ? '中篇' : '短篇'}小说，文件大小${(novel.size / 1024 / 1024).toFixed(2)}MB。`}
        </p>
        
        <div className={`mt-2 sm:mt-3 text-xs sm:text-sm ${isDarkMode ? 'text-gray-300' : 'text-gray-600'} space-y-0.5 sm:space-y-1`}>
          <p className="flex items-center">
            <span className={`inline-block w-12 sm:w-16 ${isDarkMode ? 'text-gray-400' : 'text-gray-500'}`}>大小:</span> 
            <span className="font-medium">{(novel.size / 1024 / 1024).toFixed(2)} MB</span>
          </p>
          <p className="flex items-center">
            <span className={`inline-block w-12 sm:w-16 ${isDarkMode ? 'text-gray-400' : 'text-gray-500'}`}>字数:</span> 
            <span className="font-medium">{formatWordCount(novel.wordCount || 0)}</span>
          </p>
          {readingProgress && (
            <div className={`mt-1.5 sm:mt-3 pt-1.5 sm:pt-2 border-t ${isDarkMode ? 'border-gray-700' : 'border-gray-100'}`}>
              <div className="flex items-center text-green-500 mb-1 sm:mb-2">
                <FiClock className="mr-1 sm:mr-2" />
                <span className="text-xs sm:text-sm">上次阅读: {formatDate(readingProgress.timestamp)}</span>
              </div>
              {readingProgress.totalProgress > 0 && (
                <div className={`mt-1.5 sm:mt-2 w-full ${isDarkMode ? 'bg-gray-700' : 'bg-gray-200'} rounded-full h-1.5 sm:h-2 overflow-hidden`}>
                  <div 
                    className="bg-gradient-to-r from-blue-400 to-blue-500 h-1.5 sm:h-2 rounded-full transition-all duration-500 ease-out group-hover:from-blue-500 group-hover:to-blue-600" 
                    style={{ width: `${readingProgress.totalProgress}%` }}
                  ></div>
                </div>
              )}
            </div>
          )}
        </div>
      </div>
    </div>
  );
});

// 单个小说行组件，用于表格视图
const NovelRow = memo(({ novel, isFavorite, readingProgress, onToggleFavorite, onRead }) => {
  return (
    <tr 
      className="hover:bg-gray-50 cursor-pointer"
      onClick={() => onRead(novel, readingProgress)}
    >
      <td className="px-6 py-4 whitespace-nowrap">
        <div className="flex items-center">
          <button 
            className="mr-2 text-yellow-500"
            onClick={(e) => {
              e.stopPropagation();
              onToggleFavorite(novel.id);
            }}
          >
            {isFavorite ? '★' : '☆'}
          </button>
          <div className="text-sm font-medium text-gray-900">{novel.name}</div>
          {novel.cached && (
            <span className="ml-2 text-green-500" title="已缓存，可离线阅读">
              <FiDownload />
            </span>
          )}
        </div>
      </td>
      <td className="px-6 py-4 whitespace-nowrap">
        <div className="text-sm text-gray-500">{formatWordCount(novel.wordCount || 0)}</div>
      </td>
      <td className="px-6 py-4 whitespace-nowrap">
        <div className="text-sm text-gray-500">{(novel.size / 1024 / 1024).toFixed(2)} MB</div>
      </td>
      <td className="px-6 py-4 whitespace-nowrap">
        {readingProgress ? (
          <div className="flex flex-col">
            <span className="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">
              已读 {readingProgress.totalProgress || 0}%
            </span>
            <span className="text-xs text-gray-500 mt-1">
              {formatDate(readingProgress.timestamp)}
            </span>
          </div>
        ) : (
          <span className="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">
            未读
          </span>
        )}
      </td>
      <td className="px-6 py-4 whitespace-nowrap text-sm font-medium">
        <button
          className="text-blue-600 hover:text-blue-900 mr-3"
          onClick={(e) => {
            e.stopPropagation();
            onToggleFavorite(novel.id);
          }}
        >
          {isFavorite ? '取消收藏' : '收藏'}
        </button>
      </td>
    </tr>
  );
});

// 获取网格列数对应的CSS类 - 移动到组件外部
function getGridColumnsClass(gridColumns) {
  // 移动设备上使用更紧凑的布局
  switch(gridColumns) {
    case 2:
      return "grid-cols-2 sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-2";
    case 3:
      return "grid-cols-3 sm:grid-cols-3 lg:grid-cols-3 xl:grid-cols-3";
    case 4:
      return "grid-cols-4 sm:grid-cols-4 lg:grid-cols-4 xl:grid-cols-4";
    case 5:
      return "grid-cols-5 sm:grid-cols-5 lg:grid-cols-5 xl:grid-cols-5";
    case 6:
      return "grid-cols-6 sm:grid-cols-6 lg:grid-cols-6 xl:grid-cols-6";
    default:
      return "grid-cols-3 sm:grid-cols-3 lg:grid-cols-3 xl:grid-cols-3";
  }
}

// 全局数据缓存，保持在组件外部
const globalCache = {
  novels: null,
  recentReads: null,
  recentReadsNovels: {},
  lastFetchTime: 0
};

// 选择最近阅读项的钩子函数
const useRecentReads = () => {
  const [recentReads, setRecentReads] = useState([]);
  const [recentReadsNovels, setRecentReadsNovels] = useState({});
  
  // 获取最近阅读记录的方法
  const fetchRecentReads = useCallback(async () => {
    try {
      // 尝试从本地数据库获取最近阅读记录
      let recentProgress = [];
      try {
        recentProgress = await progressOperations.getRecentReadingList(10);
      } catch (dbError) {
        console.error('从数据库获取最近阅读记录失败:', dbError);
        // 如果出错，使用空数组，不会阻止整个流程
        recentProgress = [];
      }
      
      setRecentReads(recentProgress);
      
      // 如果没有记录，不需要进一步处理
      if (!recentProgress.length) {
        return;
      }
      
      // 为每条记录获取小说信息
      const novels = {};
      for (const progress of recentProgress) {
        try {
          if (!novels[progress.novelId]) {
            const novel = await novelOperations.getNovel(progress.novelId);
            if (novel) {
              novels[progress.novelId] = novel;
            }
          }
        } catch (err) {
          console.error(`获取小说信息失败: ${progress.novelId}`, err);
        }
      }
      
      setRecentReadsNovels(novels);
    } catch (err) {
      console.error('获取最近阅读记录失败:', err);
      // 失败时设置为空数组，保证UI不会崩溃
      setRecentReads([]);
      setRecentReadsNovels({});
    }
  }, []);
  
  // 初始化时获取数据
  useEffect(() => {
    fetchRecentReads();
  }, [fetchRecentReads]);
  
  return { recentReads, recentReadsNovels, fetchRecentReads, setRecentReads, setRecentReadsNovels };
};

// 添加确认对话框组件
const ConfirmDialog = ({ isOpen, title, message, onConfirm, onCancel }) => {
  if (!isOpen) return null;
  
  return (
    <div className="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4">
      <div className="bg-white rounded-lg shadow-xl max-w-md w-full dark:bg-gray-800">
        <div className="px-6 py-4">
          <h3 className="text-lg font-medium text-gray-900 dark:text-white mb-2">{title}</h3>
          <p className="text-gray-600 dark:text-gray-300 whitespace-pre-line">{message}</p>
        </div>
        <div className="px-6 py-3 bg-gray-50 dark:bg-gray-700 rounded-b-lg flex justify-end space-x-3">
          <button
            onClick={onCancel}
            className="px-4 py-2 rounded text-gray-600 bg-gray-200 hover:bg-gray-300 dark:text-gray-300 dark:bg-gray-600 dark:hover:bg-gray-500"
          >
            取消
          </button>
          <button
            onClick={onConfirm}
            className="px-4 py-2 rounded text-white bg-red-500 hover:bg-red-600"
          >
            确认
          </button>
        </div>
      </div>
    </div>
  );
};

function Bookshelf() {
  const navigate = useNavigate();
  const location = useLocation();
  const [novels, setNovels] = useState([]);
  const [filteredNovels, setFilteredNovels] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [loadingNovel, setLoadingNovel] = useState(null);
  
  // 搜索相关状态
  const [searchTerm, setSearchTerm] = useState('');
  const [searchHistory, setSearchHistory] = useState(() => {
    const savedHistory = localStorage.getItem('searchHistory');
    return savedHistory ? JSON.parse(savedHistory) : [];
  });
  const [showSearchSuggestions, setShowSearchSuggestions] = useState(false);
  const [searchSuggestions, setSearchSuggestions] = useState([]);
  const searchInputRef = useRef(null);
  
  // 排序相关状态 - 从本地存储加载初始值
  const [sortBy, setSortBy] = useState(() => {
    return localStorage.getItem('bookshelf_sortBy') || 'lastRead';
  });
  
  // 筛选相关状态
  const [minWordCount, setMinWordCount] = useState('');
  const [maxWordCount, setMaxWordCount] = useState('');
  
  // 视图相关状态 - 从本地存储加载初始值
  const [viewMode, setViewMode] = useState(() => {
    return localStorage.getItem('bookshelf_viewMode') || 'grid';
  });
  const [gridColumns, setGridColumns] = useState(() => {
    const saved = localStorage.getItem('bookshelf_gridColumns');
    return saved ? parseInt(saved, 10) : 3;
  });
  const [sidebarCollapsed, setSidebarCollapsed] = useState(() => {
    // 移动设备默认收起，或从本地存储加载
    if (window.innerWidth < 768) return true;
    const saved = localStorage.getItem('bookshelf_sidebarCollapsed');
    return saved ? saved === 'true' : false;
  });
  
  // 收藏相关状态
  const [favorites, setFavorites] = useState(() => {
    const saved = localStorage.getItem('bookshelf_favorites');
    return saved ? JSON.parse(saved) : [];
  });
  const [showOnlyFavorites, setShowOnlyFavorites] = useState(() => {
    return localStorage.getItem('bookshelf_showOnlyFavorites') === 'true';
  });
  
  // 最近阅读相关状态
  const { recentReads, recentReadsNovels, fetchRecentReads, setRecentReads, setRecentReadsNovels } = useRecentReads();
  const [showReadingPopup, setShowReadingPopup] = useState(false);
  
  // 分页相关状态
  const [currentPage, setCurrentPage] = useState(1);
  const [itemsPerPage, setItemsPerPage] = useState(30);
  
  // 加载状态
  const [isFiltering, setIsFiltering] = useState(false);
  const [isScanningLoading, setIsScanningLoading] = useState(false);
  
  // 增加一个快速访问的网格设置按钮状态
  const [showGridSettings, setShowGridSettings] = useState(false);
  
  // 页面挂载识别
  const [isInitialRender, setIsInitialRender] = useState(true);
  const hasDataRef = useRef(novels.length > 0);
  
  // 离线模式相关状态
  const [isOfflineMode, setIsOfflineMode] = useState(localStorage.getItem('offlineMode') === 'true');
  const [showOfflineManager, setShowOfflineManager] = useState(false);
  const [cacheStats, setCacheStats] = useState(null);
  const [selectedNovels, setSelectedNovels] = useState([]);
  const [isCaching, setIsCaching] = useState(false);
  const [cacheProgress, setCacheProgress] = useState(null);
  
  // 确认对话框状态
  const [confirmDialog, setConfirmDialog] = useState({
    isOpen: false,
    title: '',
    message: '',
    onConfirm: () => {},
    onCancel: () => {}
  });
  
  const { isDarkMode, toggleTheme } = useTheme();
  
  // 添加fadeIn状态
  const [fadeIn, setFadeIn] = useState(false);
  
  // 添加从阅读页面返回的状态，用于避免重复刷新
  const [returnFromReader, setReturnFromReader] = useState(false);
  const returnFromReaderRef = useRef(false);
  
  // 提前声明fetchNovels函数引用，解决循环依赖问题
  const fetchNovelsRef = useRef(null);
  // 添加请求锁，防止重复请求
  const isRequestingRef = useRef(false);
  
  // 添加上下文菜单状态
  const [contextMenu, setContextMenu] = useState({ show: false, x: 0, y: 0, novel: null, items: [] });
  
  // 在页面加载后启用渐入效果
  useEffect(() => {
    setTimeout(() => {
      setFadeIn(true);
    }, 100);
  }, []);
  
  // 加载小说数据 - 使用缓存减少闪烁
  const fetchNovels = useCallback(async () => {
    // 防止重复请求
    if (isRequestingRef.current) {
      console.log('已有请求正在处理中，跳过重复请求');
      return;
    }
    
    // 如果是从阅读页面返回，不重新加载数据
    if (returnFromReader || returnFromReaderRef.current) {
      console.log('从阅读页返回，跳过数据加载');
      // 只更新阅读进度
      fetchRecentReads().catch(console.error);
      return;
    }
    
    // 设置请求锁
    isRequestingRef.current = true;
    
    // 设置超时检测
    const timeout = setTimeout(() => {
      console.log('获取小说列表超时，强制显示界面');
      setLoading(false);
      if (novels.length === 0) {
        setError('加载超时，请刷新页面重试。如果问题持续存在，请尝试清除浏览器缓存。');
      }
    }, 10000); // 10秒超时
    
    try {
      console.log('开始获取小说列表...');
      
      // 显式设置加载状态
      setLoading(true);
      
      // 如果有缓存数据且在30分钟内，不重新加载
      const now = Date.now();
      const cacheAge = now - (globalCache.lastFetchTime || 0);
      const cacheValid = cacheAge < 30 * 60 * 1000; // 30分钟缓存

      if (globalCache.novels && globalCache.novels.length > 0 && cacheValid && !isInitialRender) {
        // 直接使用缓存数据
        console.log('使用全局缓存的小说列表数据', globalCache.novels);
        setNovels(globalCache.novels);
        setFilteredNovels(globalCache.novels);
        clearTimeout(timeout); // 清除超时
        setLoading(false);
        isRequestingRef.current = false; // 释放请求锁
        return;
      }

      // 如果是从阅读页面返回，使用现有数据减少闪烁
      if (!isInitialRender && novels.length > 0) {
        // 仅异步更新最近阅读进度
        fetchRecentReads().catch(console.error);
        clearTimeout(timeout); // 清除超时
        isRequestingRef.current = false; // 释放请求锁
        return;
      }
      
      // 获取小说列表 - 添加错误处理
      let data;
      try {
        console.log('从API获取小说列表...');
        
        // 检查是否处于离线模式
        if (isOfflineMode) {
          console.log('离线模式下，仅从本地数据库获取已缓存的小说');
          const localNovels = await novelOperations.getAllNovels();
          
          if (localNovels && localNovels.length > 0) {
            console.log(`从本地获取到 ${localNovels.length} 本小说`);
            
            // 获取缓存状态，筛选出已缓存的小说
            const cachedNovels = [];
            for (const novel of localNovels) {
              try {
                const isCached = await novelOperations.isNovelCached(novel.id);
                if (isCached) {
                  cachedNovels.push({ ...novel, cached: true });
                }
              } catch (err) {
                console.error(`检查小说 ${novel.id} 缓存状态失败:`, err);
              }
            }
            
            console.log(`离线模式下，共有 ${cachedNovels.length} 本已缓存的小说`);
            data = cachedNovels;
          } else {
            console.log('本地数据库中没有小说');
            data = [];
          }
        } else {
          // 在线模式，正常从API获取
          data = await novelsApi.getAll();
          console.log('API返回小说列表: ', data);
        }
      } catch (apiError) {
        console.error('API获取小说列表失败:', apiError);
        // 如果API请求失败，尝试从本地数据库获取
        console.log('尝试从本地数据库获取小说列表...');
        const localNovels = await novelOperations.getAllNovels();
        if (localNovels && localNovels.length > 0) {
          console.log('使用本地数据库的小说列表:', localNovels);
          
          // 如果处于离线模式，只显示已缓存的小说
          if (isOfflineMode) {
            const cachedNovels = [];
            for (const novel of localNovels) {
              try {
                const isCached = await novelOperations.isNovelCached(novel.id);
                if (isCached) {
                  cachedNovels.push({ ...novel, cached: true });
                }
              } catch (err) {
                console.error(`检查小说 ${novel.id} 缓存状态失败:`, err);
              }
            }
            data = cachedNovels;
          } else {
            data = localNovels;
          }
        } else {
          throw new Error('无法从API和本地获取小说列表');
        }
      }
      
      // 直接设置小说列表，先不进行缓存状态检查，确保UI可见
      setNovels(data);
      setFilteredNovels(data);
      
      // 获取每本小说的缓存状态 - 优化为批量操作
      const batchSize = 20; // 批量处理的大小
      const novelsWithCacheStatus = [];
      
      for (let i = 0; i < data.length; i += batchSize) {
        const batch = data.slice(i, i + batchSize);
        const batchResults = await Promise.all(
          batch.map(async (novel) => {
            try {
              const isCached = await novelOperations.isNovelCached(novel.id);
              return { ...novel, cached: isCached };
            } catch (err) {
              console.error(`获取小说 ${novel.id} 缓存状态失败:`, err);
              return { ...novel, cached: false };
            }
          })
        );
        novelsWithCacheStatus.push(...batchResults);
        
        // 对于大列表，提前更新界面以提高响应性
        if (i === 0 && data.length > batchSize * 2) {
          setNovels([...novelsWithCacheStatus]);
          setFilteredNovels([...novelsWithCacheStatus]);
        }
      }
      
      // 更新全局缓存
      globalCache.novels = novelsWithCacheStatus;
      globalCache.lastFetchTime = now;
      
      console.log('小说列表加载和缓存状态处理完毕:', novelsWithCacheStatus.length);
      setNovels(novelsWithCacheStatus);
      setFilteredNovels(novelsWithCacheStatus);
      clearTimeout(timeout); // 清除超时
      setLoading(false);
      
      // 获取最近阅读记录
      await fetchRecentReads().catch(err => {
        console.error('获取最近阅读记录失败，但不影响列表显示:', err);
      });
    } catch (err) {
      console.error('获取小说列表失败:', err);
      setError('无法加载小说列表，请检查后端服务是否运行');
      clearTimeout(timeout); // 清除超时
      setLoading(false);
    } finally {
      // 释放请求锁
      isRequestingRef.current = false;
      // 修改初始渲染标记
      setIsInitialRender(false);
    }
  }, [isInitialRender, fetchRecentReads, returnFromReader, isOfflineMode]); // 移除 novels.length 依赖项
  
  // 确保在进入页面后立即加载小说列表
  useEffect(() => {
    if (!returnFromReader && !returnFromReaderRef.current) {
      console.log('组件挂载，立即加载小说列表');
      fetchNovels();
    }
  }, [fetchNovels, returnFromReader]);
  
  // 将函数引用保存到ref中，以便在其他地方使用
  useEffect(() => {
    fetchNovelsRef.current = fetchNovels;
  }, [fetchNovels]);

  // 检测是否从阅读页面返回
  useEffect(() => {
    // 检查location.state是否包含从阅读页面返回的标记
    if (location.state?.fromReader) {
      console.log('检测到从阅读页面返回');
      setReturnFromReader(true);
      returnFromReaderRef.current = true;
      
      // 检查是否需要切换到离线模式
      if (location.state?.switchToOfflineMode && !isOfflineMode) {
        console.log('根据要求切换到离线书架模式');
        setIsOfflineMode(true);
        localStorage.setItem('offlineMode', 'true');
        
        // 提示用户已切换到离线模式
        setError('已切换到本地书架模式，现在只显示已缓存的小说');
        setTimeout(() => setError(null), 3000); // 3秒后自动关闭提示
      }
      
      // 清除state以避免影响之后的导航，但保留fromReader状态直到页面刷新
      const newState = { ...location.state, fromReader: true };
      window.history.replaceState(newState, document.title);
      
      // 只异步更新最近阅读状态，不重新加载列表
      fetchRecentReads().catch(console.error);
      
      // 更新当前列表的阅读状态
      if (novels.length > 0) {
        console.log('从阅读页返回：仅更新阅读状态，不重新加载列表');
      }
    }
  }, [location, fetchRecentReads, novels.length, isOfflineMode]);
  
  // 初始化加载
  useEffect(() => {
    // 如果是从阅读页面返回，不执行初始化加载
    if (returnFromReader || returnFromReaderRef.current) {
      console.log('从阅读页返回，跳过初始化加载');
      setLoading(false);
      return;
    }

    // 防止和普通的fetchNovels冲突，只在未进行请求时执行
    if (!isRequestingRef.current) {
      console.log('执行正常的fetchNovels加载流程');
      fetchNovels();
    }

    // 移除直接初始化加载部分，避免重复API调用
    // const directInitializeLoad = async () => { ... }
    // directInitializeLoad();
    
    // 总是设置为非初始渲染，确保后续更新不会再次触发初始化
    setIsInitialRender(false);
  }, [returnFromReader, fetchNovels]);
  
  // 使用useMemo优化筛选和排序，避免每次渲染都重新计算
  useMemo(() => {
    if (novels.length === 0) {
      console.log('novels数组为空，跳过筛选');
      return;
    }
    
    console.log(`开始筛选 ${novels.length} 本小说`, novels);
    
    // 设置筛选状态，可用于显示加载中指示器
    setIsFiltering(true);
    
    // 使用setTimeout使UI有机会在繁重计算前更新
    setTimeout(() => {
      try {
        // 先按筛选条件过滤
        let result = [...novels];
        console.log(`筛选前：${result.length} 本小说`);
        
        // 应用搜索
        if (searchTerm.trim() !== '') {
          const term = searchTerm.toLowerCase();
          result = result.filter(novel => 
            novel.name.toLowerCase().includes(term)
          );
          console.log(`搜索筛选后：${result.length} 本小说`);
        }
        
        // 应用字数范围筛选
        if (minWordCount !== '') {
          const min = parseInt(minWordCount, 10);
          if (!isNaN(min)) {
            result = result.filter(novel => (novel.wordCount || 0) >= min);
          }
          console.log(`最小字数筛选后：${result.length} 本小说`);
        }
        
        if (maxWordCount !== '') {
          const max = parseInt(maxWordCount, 10);
          if (!isNaN(max)) {
            result = result.filter(novel => (novel.wordCount || 0) <= max);
          }
          console.log(`最大字数筛选后：${result.length} 本小说`);
        }
        
        // 应用收藏筛选
        if (showOnlyFavorites) {
          result = result.filter(novel => favorites.includes(novel.id));
          console.log(`收藏筛选后：${result.length} 本小说`);
        }
        
        // 移除错误的最近阅读筛选 - 这会过滤掉所有不在最近阅读列表中的小说
        // 只有当用户明确选择了"最近阅读"选项卡时才应用这个筛选
        // 最近阅读应该在单独的Tab中显示，而不是筛选所有小说
        
        // 应用排序
        if (sortBy === 'wordCount-asc') {
          result.sort((a, b) => (a.wordCount || 0) - (b.wordCount || 0));
        } else if (sortBy === 'wordCount-desc') {
          result.sort((a, b) => (b.wordCount || 0) - (a.wordCount || 0));
        } else if (sortBy === 'name') {
          result.sort((a, b) => a.name.localeCompare(b.name));
        } else if (sortBy === 'size') {
          result.sort((a, b) => b.size - a.size);
        } else if (sortBy === 'lastRead') {
          // 按最后阅读时间排序，优化排序逻辑
          const novelReadTimes = {};
          
          // 预先计算每本小说的最后阅读时间，避免在排序中重复查找
          recentReads.forEach(item => {
            novelReadTimes[item.novelId] = item.timestamp;
          });
          
          result.sort((a, b) => {
            const aTime = novelReadTimes[a.id] || 0;
            const bTime = novelReadTimes[b.id] || 0;
            return bTime - aTime; // 降序排列，最近阅读的排在前面
          });
        }
        
        console.log(`最终筛选和排序后：${result.length} 本小说`, result);
        
        // 强制确保result不为空数组以便debug
        if (result.length === 0 && novels.length > 0 && !searchTerm && !minWordCount && !maxWordCount && !showOnlyFavorites) {
          console.warn('筛选结果为空但原始数据不为空，可能存在筛选逻辑问题，使用原始数据');
          result = [...novels];
        }
        
        setFilteredNovels(result);
        setCurrentPage(1); // 重置为第一页
      } catch (err) {
        console.error('筛选小说时出错:', err);
        // 出错时使用原始数据
        setFilteredNovels([...novels]);
      } finally {
        setIsFiltering(false); // 筛选完成
      }
    }, 0);
  }, [novels, sortBy, minWordCount, maxWordCount, searchTerm, favorites, showOnlyFavorites, recentReads]);

  // 确保在调试窗口显示当前状态
  useEffect(() => {
    console.log('当前状态:', {
      novels: novels.length,
      filteredNovels: filteredNovels.length,
      currentPage,
      itemsPerPage,
      loading,
      isFiltering
    });
  }, [novels, filteredNovels, currentPage, itemsPerPage, loading, isFiltering]);

  // 获取当前页的数据
  const currentPageData = useMemo(() => {
    const startIndex = (currentPage - 1) * itemsPerPage;
    const result = filteredNovels.slice(startIndex, startIndex + itemsPerPage);
    console.log(`当前页数据: 第${currentPage}页，显示${result.length}本小说，总共${filteredNovels.length}本`);
    return result;
  }, [filteredNovels, currentPage, itemsPerPage]);

  // 计算总页数
  const totalPages = useMemo(() => {
    return Math.ceil(filteredNovels.length / itemsPerPage);
  }, [filteredNovels, itemsPerPage]);
  
  // 生成页码数组
  const pageNumbers = useMemo(() => {
    const isMobile = window.innerWidth < 640; // 判断是否为移动设备
    const totalPageNumbers = isMobile ? 3 : 5; // 移动设备显示更少的页码
    const pages = [];
    
    if (totalPages <= totalPageNumbers) {
      // 如果总页数少于要显示的数量，则显示所有页码
      for (let i = 1; i <= totalPages; i++) {
        pages.push({ type: 'page', number: i });
      }
    } else {
      // 始终显示第一页
      pages.push({ type: 'page', number: 1 });
      
      // 计算当前页码左右两侧显示的页码数量
      const leftSide = Math.floor(totalPageNumbers / 2);
      const rightSide = totalPageNumbers - leftSide - 1;
      
      // 计算当前页左右的页码范围
      let startPage = Math.max(2, currentPage - leftSide);
      let endPage = Math.min(totalPages - 1, currentPage + rightSide);
      
      // 如果范围失衡，则调整
      if (startPage <= 2) {
        endPage = Math.min(totalPageNumbers, totalPages - 1);
      }
      
      if (endPage >= totalPages - 1) {
        startPage = Math.max(2, totalPages - totalPageNumbers + 1);
      }
      
      // 添加左侧省略号
      if (startPage > 2) {
        pages.push({ type: 'ellipsis', number: null });
      }
      
      // 添加中间页码
      for (let i = startPage; i <= endPage; i++) {
        pages.push({ type: 'page', number: i });
      }
      
      // 添加右侧省略号
      if (endPage < totalPages - 1) {
        pages.push({ type: 'ellipsis', number: null });
      }
      
      // 始终显示最后一页
      pages.push({ type: 'page', number: totalPages });
    }
    
    return pages;
  }, [totalPages, currentPage]);
  
  // 处理阅读小说
  const handleRead = useCallback((novel, readingProgress = null) => {
    navigate(`/reader/${novel.id}`);
  }, [navigate]);
  
  // 处理收藏切换
  const handleToggleFavorite = useCallback((novelId) => {
    setFavorites(prev => {
      return prev.includes(novelId) 
        ? prev.filter(id => id !== novelId)
        : [...prev, novelId];
    });
  }, []);
  
  // 触发扫描
  const handleScan = async () => {
    try {
      setIsScanningLoading(true);
      await novelsApi.triggerScan();
      
      // 重新加载小说列表
      const data = await novelsApi.getAll();
      setNovels(data);
      setFilteredNovels(data);
      
      setIsScanningLoading(false);
    } catch (err) {
      console.error('触发扫描失败:', err);
      setError('扫描失败，请检查后端服务是否运行');
      setIsScanningLoading(false);
    }
  };
  
  // 查找小说的阅读进度
  const getReadingProgress = useCallback((novelId) => {
    return recentReads.find(item => item.novelId === novelId);
  }, [recentReads]);
  
  // 使用虚拟列表渲染小说
  const renderNovelCard = (novel, index) => (
    <NovelCard 
      key={novel.id || index}
      novel={novel}
      isFavorite={favorites.includes(novel.id)}
      readingProgress={getReadingProgress(novel.id)}
      onToggleFavorite={handleToggleFavorite}
      onRead={handleRead}
    />
  );
  
  // 处理搜索
  const handleSearch = (term) => {
    if (!term.trim()) return;
    
    // 保存到搜索历史
    if (!searchHistory.includes(term)) {
      const newHistory = [term, ...searchHistory.slice(0, 9)];
      setSearchHistory(newHistory);
      localStorage.setItem('searchHistory', JSON.stringify(newHistory));
    }
    
    setSearchTerm(term);
    setShowSearchSuggestions(false);
  };
  
  // 清除搜索历史
  const clearSearchHistory = () => {
    setSearchHistory([]);
    localStorage.removeItem('searchHistory');
  };
  
  // 生成搜索建议
  useEffect(() => {
    if (searchTerm.trim().length > 0) {
      // 从小说列表和历史搜索中生成建议
      const suggestions = [];
      
      // 从历史中添加匹配的搜索
      searchHistory.forEach(history => {
        if (history.toLowerCase().includes(searchTerm.toLowerCase()) && !suggestions.includes(history)) {
          suggestions.push(history);
        }
      });
      
      // 从小说标题中添加匹配项
      novels.forEach(novel => {
        if (novel.name.toLowerCase().includes(searchTerm.toLowerCase())) {
          const suggestion = novel.name;
          if (!suggestions.includes(suggestion)) {
            suggestions.push(suggestion);
          }
        }
      });
      
      setSearchSuggestions(suggestions.slice(0, 5));
      setShowSearchSuggestions(suggestions.length > 0);
    } else {
      setShowSearchSuggestions(false);
    }
  }, [searchTerm, novels, searchHistory]);
  
  // 监听点击事件关闭搜索建议
  useEffect(() => {
    const handleClickOutside = (event) => {
      if (searchInputRef.current && !searchInputRef.current.contains(event.target)) {
        setShowSearchSuggestions(false);
      }
    };
    
    document.addEventListener('mousedown', handleClickOutside);
    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
    };
  }, [searchInputRef]);
  
  // 监听键盘快捷键
  useEffect(() => {
    const handleKeyDown = (e) => {
      // 按下 / 键聚焦搜索框
      if (e.key === '/' && document.activeElement.tagName !== 'INPUT') {
        e.preventDefault();
        searchInputRef.current?.focus();
      }
    };
    
    document.addEventListener('keydown', handleKeyDown);
    return () => {
      document.removeEventListener('keydown', handleKeyDown);
    };
  }, []);
  
  // 刷新缓存统计数据
  const refreshCacheStats = useCallback(async () => {
    try {
      // 设置加载状态
      setCacheStats(null);
      
      // 添加超时防止无限等待
      const statsPromise = novelOperations.getCacheStats();
      const timeoutPromise = new Promise((_, reject) => 
        setTimeout(() => reject(new Error('获取缓存统计超时')), 5000)
      );
      
      // 使用Promise.race确保不会无限等待
      const stats = await Promise.race([statsPromise, timeoutPromise]);
      setCacheStats(stats);
    } catch (err) {
      console.error('刷新缓存统计失败:', err);
      setCacheStats({ error: err.message || '获取统计信息失败' });
    }
  }, []);
  
  // 在组件加载时获取缓存统计
  useEffect(() => {
    refreshCacheStats();
  }, [refreshCacheStats]);
  
  // 批量缓存选中的小说
  const cacheSelectedNovel = useCallback(async () => {
    if (selectedNovels.length === 0) return;
    
    try {
      setIsCaching(true);
      setCacheProgress({
        current: 0,
        total: selectedNovels.length,
        percentage: 0
      });
      
      // 使用预缓存功能批量缓存
      await novelOperations.preCacheNovelList(
        selectedNovels,
        {
          progressCallback: (progress) => {
            setCacheProgress(progress);
          }
        }
      );
      
      // 刷新小说列表和缓存统计
      fetchNovels();
      refreshCacheStats();
      
      // 清除选择
      setSelectedNovels([]);
    } catch (err) {
      console.error('批量缓存失败:', err);
    } finally {
      setIsCaching(false);
    }
  }, [selectedNovels, fetchNovels, refreshCacheStats]);
  
  // 清除所有缓存
  const clearAllCache = async () => {
    if (!window.confirm('确定要清除所有缓存的小说吗？这将释放存储空间，但需要网络连接才能再次阅读这些小说。')) {
      return;
    }
    
    try {
      setLoading(true);
      
      // 获取所有已缓存的小说
      const cachedNovels = await db.novels
        .where('cached')
        .equals(true)
        .toArray();
      
      // 清除每本小说的缓存
      for (const novel of cachedNovels) {
        await db.transaction('rw', [db.novels, db.contents], async () => {
          // 删除内容但保留小说信息和阅读进度
          await db.contents.where('novelId').equals(novel.id).delete();
          await db.novels.update(novel.id, { cached: false });
        });
      }
      
      console.log(`已清除 ${cachedNovels.length} 本小说的缓存`);
      
      // 刷新统计和小说列表
      refreshCacheStats();
      fetchNovels();
    } catch (err) {
      console.error('清除缓存失败:', err);
    } finally {
      setLoading(false);
    }
  };
  
  // 切换小说选择
  const toggleNovelSelection = useCallback((id) => {
    setSelectedNovels(prev => {
      if (prev.includes(id)) {
        return prev.filter(item => item !== id);
      } else {
        return [...prev, id];
      }
    });
  }, []);
  
  // 切换离线模式
  const toggleOfflineMode = () => {
    const newMode = !isOfflineMode;
    
    // 如果是切换到离线模式，弹出提示
    if (newMode && !isOfflineMode) {
      if (window.confirm('是否切换到本地书架模式？\n\n在本地书架模式下，您只能访问已缓存的小说。')) {
        setIsOfflineMode(newMode);
        localStorage.setItem('offlineMode', String(newMode));
        
        // 提示用户已切换到离线模式
        setError('已切换到本地书架模式，现在只显示已缓存的小说');
        setTimeout(() => setError(null), 3000); // 3秒后自动关闭提示
        
        // 刷新小说列表，只显示已缓存的书籍
        fetchNovels();
      }
    } else {
      // 切换回在线模式或用户取消了切换
      setIsOfflineMode(newMode);
      localStorage.setItem('offlineMode', String(newMode));
      
      if (!newMode) {
        // 提示用户已切换回在线模式
        setError('已切换回在线模式，将显示所有小说');
        setTimeout(() => setError(null), 3000); // 3秒后自动关闭提示
      }
      
      // 刷新小说列表
      fetchNovels();
    }
  };
  
  // 专门处理单本小说缓存的函数
  const handleCacheNovel = async (novel) => {
    try {
      if (!novel || !novel.id) {
        alert('无效的小说');
        return;
      }

      const isCached = await novelOperations.isNovelCached(novel.id);
      if (isCached) {
        alert(`《${novel.title || novel.name}》已经缓存，无需重复缓存。`);
        return;
      }

      // 显示加载中状态
      setLoadingNovel(novel.id);

      // 获取完整内容并缓存
      const contentResponse = await novelsApi.getFullNovelContent(novel.id);
      if (!contentResponse || !contentResponse.content) {
        throw new Error("获取小说内容失败");
      }

      // 使用正确的内容数据进行缓存
      await novelOperations.cacheNovel(novel, contentResponse.content);
      
      // 再次验证缓存是否成功
      const verifyCached = await novelOperations.isNovelCached(novel.id);
      if (!verifyCached) {
        throw new Error("缓存验证失败，请重试");
      }
      
      // 更新全局缓存和UI状态
      updateNovelCacheStatus(novel.id, true);
      
      // 更新缓存统计
      refreshCacheStats();
      
      setLoadingNovel(null);
      alert(`《${novel.title || novel.name}》缓存成功！`);
    } catch (error) {
      console.error("缓存小说失败", error);
      setLoadingNovel(null);
      alert(`缓存失败: ${error.message || "未知错误"}`);
    }
  };
  
  // 在useEffect中处理来自Reader页面的修复数据库请求
  useEffect(() => {
    const handleRouteState = () => {
      if (location.state) {
        const { openRepairDialog, invalidNovelId } = location.state;
        
        if (openRepairDialog) {
          // 延迟执行，确保组件已完全加载
          setTimeout(() => {
            repairSpecificNovel(invalidNovelId);
          }, 500);
          
          // 清除state，避免刷新页面时重复执行
          navigate('/', { replace: true, state: {} });
        }
      }
    };
    
    handleRouteState();
  }, [location, navigate]);
  
  // 修复特定小说的函数
  const repairSpecificNovel = async (novelId) => {
    if (!novelId) {
      repairDatabase();
      return;
    }
    
    // 先获取小说名称
    let novelName = `ID: ${novelId}`;
    try {
      const novel = await novelOperations.getNovel(novelId);
      if (novel) {
        novelName = novel.name;
      }
    } catch (err) {
      console.error('获取小说信息失败:', err);
    }
    
    setConfirmDialog({
      isOpen: true,
      title: '删除小说记录',
      message: `确定要删除小说《${novelName}》的记录吗？该操作将清理此小说在本地的所有数据，包括阅读进度。`,
      onConfirm: async () => {
        setConfirmDialog({ ...confirmDialog, isOpen: false });
        
        try {
          setLoading(true);
          
          // 删除小说
          await novelOperations.deleteNovel(novelId);
          
          alert(`已成功删除小说《${novelName}》的本地数据`);
          
          // 刷新小说列表
          await fetchNovels();
        } catch (err) {
          console.error('删除小说失败:', err);
          alert(`删除小说失败: ${err.message}`);
        } finally {
          setLoading(false);
        }
      },
      onCancel: () => {
        setConfirmDialog({ ...confirmDialog, isOpen: false });
      }
    });
  };
  
  // 修改repairDatabase函数，使用确认对话框组件
  const repairDatabase = async () => {
    setConfirmDialog({
      isOpen: true,
      title: '修复数据库',
      message: '此操作将检查并清理数据库中的无效记录，可能会删除一些本地数据。是否继续？',
      onConfirm: async () => {
        setConfirmDialog({ ...confirmDialog, isOpen: false });
        
        try {
          setLoading(true);
          
          // 1. 获取所有本地小说
          console.log('获取本地小说列表...');
          const localNovels = await novelOperations.getAllNovels();
          console.log(`发现 ${localNovels.length} 本本地小说`);
          
          // 2. 验证每本小说是否可以从服务器获取
          const invalidNovels = [];
          
          for (const novel of localNovels) {
            try {
              // 尝试从服务器获取小说信息
              const response = await fetch(`${process.env.REACT_APP_API_URL || 'http://localhost:3001/api'}/novels/${novel.id}`);
              if (!response.ok) {
                console.log(`小说 ${novel.id} (${novel.name}) 在服务器上不存在`);
                invalidNovels.push(novel);
              }
            } catch (err) {
              console.error(`检查小说 ${novel.id} 时出错:`, err);
            }
          }
          
          // 3. 删除无效的小说记录
          if (invalidNovels.length > 0) {
            console.log(`准备删除 ${invalidNovels.length} 本无效小说`, invalidNovels);
            
            for (const novel of invalidNovels) {
              try {
                // 删除相关数据
                await novelOperations.deleteNovel(novel.id);
                console.log(`已删除小说: ${novel.id} (${novel.name})`);
              } catch (deleteErr) {
                console.error(`删除小说 ${novel.id} 失败:`, deleteErr);
              }
            }
            
            alert(`数据库修复完成，已删除 ${invalidNovels.length} 本无效小说记录`);
          } else {
            alert('数据库检查完成，未发现需要修复的问题');
          }
          
          // 4. 刷新小说列表
          await fetchNovels();
        } catch (err) {
          console.error('修复数据库失败:', err);
          alert(`修复数据库失败: ${err.message}`);
        } finally {
          setLoading(false);
        }
      },
      onCancel: () => {
        setConfirmDialog({ ...confirmDialog, isOpen: false });
      }
    });
  };
  
  // 重置数据库函数
  const resetDatabase = async () => {
    setConfirmDialog({
      isOpen: true,
      title: '重置数据库',
      message: '此操作将清空所有本地数据，包括所有缓存的小说、阅读进度和设置。此操作不可逆！\n\n确定要完全重置数据库吗？',
      onConfirm: async () => {
        setConfirmDialog({ ...confirmDialog, isOpen: false });
        
        try {
          setLoading(true);
          
          // 调用数据库重置方法
          const result = await db.resetDatabase();
          
          if (result.status === 'success') {
            alert('数据库已成功重置，将重新加载页面。');
            // 刷新页面以重新初始化应用
            window.location.reload();
          } else {
            alert(`重置失败: ${result.message}`);
            // 刷新小说列表
            fetchNovels();
          }
        } catch (err) {
          console.error('重置数据库失败:', err);
          alert(`重置数据库失败: ${err.message}`);
          setLoading(false);
        }
      },
      onCancel: () => {
        setConfirmDialog({ ...confirmDialog, isOpen: false });
      }
    });
  };
  
  // 添加数据状态检查，确保数据正确显示
  useEffect(() => {
    console.log("界面数据状态检查:", {
      "原始小说数量": novels.length,
      "过滤后小说数量": filteredNovels.length,
      "当前页小说数量": currentPageData.length,
      "当前页码": currentPage,
      "每页显示数量": itemsPerPage,
      "筛选状态": isFiltering,
    });
    
    // 如果数据可用但页面无内容，尝试重置筛选条件
    if (!loading && !isFiltering && novels.length > 0 && filteredNovels.length === 0) {
      console.warn("检测到数据问题：原始数据存在但筛选结果为空，尝试重置筛选");
      setFilteredNovels([...novels]);
    }
  }, [novels, filteredNovels, currentPageData, currentPage, itemsPerPage, loading, isFiltering]);

  // 在显示界面之前退出加载状态
  if (loading) {
    return (
      <div className="container mx-auto p-4 text-center">
        <p className="text-lg">正在加载小说列表...</p>
      </div>
    );
  }
  
  // 新增：验证缓存状态
  const validateCacheStatus = async () => {
    try {
      setLoading(true);
      
      // 获取所有标记为已缓存的小说
      const cachedNovels = await db.novels
        .where('cached')
        .equals(true)
        .toArray();
      
      console.log(`开始验证 ${cachedNovels.length} 本已缓存小说的缓存状态...`);
      
      let fixedCount = 0;
      
      // 检查每一本小说
      for (const novel of cachedNovels) {
        try {
          // 检查内容是否真的存在
          const fullContent = await db.fullContents.get({ novelId: novel.id });
          const hasChunks = await db.contents.where('novelId').equals(novel.id).count() > 0;
          
          // 如果标记为已缓存但实际上没有内容
          if ((!fullContent || !fullContent.data) && !hasChunks) {
            console.warn(`修复小说 "${novel.name}" (ID: ${novel.id})：标记为已缓存，但未找到内容`);
            
            // 修复缓存状态
            await db.novels.update(novel.id, { cached: false });
            fixedCount++;
          }
        } catch (err) {
          console.error(`验证小说 "${novel.name}" (ID: ${novel.id}) 的缓存状态失败:`, err);
        }
      }
      
      console.log(`缓存验证完成，修复了 ${fixedCount} 本小说的缓存状态`);
      
      if (fixedCount > 0) {
        // 刷新缓存状态和小说列表
        refreshCacheStats();
        fetchNovels();
        alert(`已修复 ${fixedCount} 本小说的缓存状态`);
      } else if (cachedNovels.length > 0) {
        alert('所有缓存状态正常');
      } else {
        alert('未找到已缓存的小说');
      }
    } catch (err) {
      console.error('验证缓存状态失败:', err);
      alert(`验证缓存状态时出错: ${err.message || '未知错误'}`);
    } finally {
      setLoading(false);
    }
  };
  
  // 增强：彻底修复缓存状态
  const repairAllCacheStatus = async () => {
    if (!window.confirm('此操作将重新扫描所有小说的缓存状态并修复任何不一致，这可能需要一些时间。是否继续？')) {
      return;
    }
    
    try {
      setLoading(true);
      
      // 获取所有小说
      const allNovels = await db.novels.toArray();
      console.log(`开始扫描 ${allNovels.length} 本小说的缓存状态...`);
      
      let repairCount = 0;
      let incorrectStatus = 0;
      
      // 检查每一本小说
      for (const novel of allNovels) {
        try {
          // 获取小说内容
          const fullContent = await db.fullContents.get({ novelId: novel.id });
          const hasChunks = await db.contents.where('novelId').equals(novel.id).count() > 0;
          
          // 检查是否真的有缓存内容
          const actuallyHasContent = (fullContent && fullContent.data && fullContent.data.length > 0) || hasChunks;
          
          // 缓存标记与实际内容是否一致
          if (!!novel.cached !== actuallyHasContent) {
            incorrectStatus++;
            
            // 修复不一致状态
            await db.novels.update(novel.id, { cached: actuallyHasContent });
            
            // 如果标记为缓存但实际没有内容，可能是之前内容被破坏，需要清理缓存信息
            if (novel.cached && !actuallyHasContent) {
              // 清除可能的无效缓存信息
              await db.cacheInfo.where({ novelId: novel.id }).delete();
              console.log(`小说 "${novel.name}" 标记为已缓存但实际无内容，已清除缓存信息`);
            }
            
            repairCount++;
            console.log(`修复: "${novel.name}" - 缓存标记: ${novel.cached}, 实际状态: ${actuallyHasContent}`);
          }
          
          // 如果存在分片但没有整体内容，尝试合并分片并存储
          if (hasChunks && (!fullContent || !fullContent.data)) {
            try {
              const chunks = await db.contents.where('novelId').equals(novel.id).toArray();
              if (chunks.length > 0) {
                // 按分片索引排序并合并
                chunks.sort((a, b) => (a.chunkIndex || 0) - (b.chunkIndex || 0));
                const combinedContent = chunks.map(chunk => chunk.data).join('');
                
                if (combinedContent.length > 0) {
                  // 保存合并后的内容
                  await db.fullContents.put({
                    novelId: novel.id,
                    data: combinedContent,
                    timestamp: Date.now()
                  });
                  console.log(`已将 "${novel.name}" 的 ${chunks.length} 个分片合并为完整内容`);
                  repairCount++;
                }
              }
            } catch (mergeErr) {
              console.error(`合并 "${novel.name}" 的分片内容失败:`, mergeErr);
            }
          }
        } catch (err) {
          console.error(`检查小说 "${novel.name}" 的缓存状态失败:`, err);
        }
      }
      
      console.log(`修复完成! 检查了 ${allNovels.length} 本小说，修复了 ${repairCount} 个问题，发现 ${incorrectStatus} 个缓存状态不一致。`);
      
      // 刷新缓存状态和小说列表
      refreshCacheStats();
      fetchNovels();
      
      alert(`扫描完成！共检查 ${allNovels.length} 本小说，修复了 ${repairCount} 个问题。${incorrectStatus > 0 ? `修复了 ${incorrectStatus} 个缓存状态不一致。` : ''}`);
    } catch (err) {
      console.error('修复缓存状态失败:', err);
      alert(`修复缓存状态时出错: ${err.message || '未知错误'}`);
    } finally {
      setLoading(false);
    }
  };
  
  // 修复单本小说的缓存
  const fixSingleNovelCache = async (novel) => {
    if (!novel || !novel.id) return;
    
    try {
      setLoading(true);
      
      console.log(`开始修复小说 "${novel.name}" (ID: ${novel.id}) 的缓存...`);
      
      // 首先检查内容是否存在
      const fullContent = await db.fullContents.get({ novelId: novel.id });
      const hasChunks = await db.contents.where('novelId').equals(novel.id).count() > 0;
      
      // 检查是否真的有缓存内容
      const actuallyHasContent = (fullContent && fullContent.data && fullContent.data.length > 0) || hasChunks;
      
      // 如果标记与实际内容不一致，修复标记
      if (!!novel.cached !== actuallyHasContent) {
        await db.novels.update(novel.id, { cached: actuallyHasContent });
        console.log(`已修复小说 "${novel.name}" 的缓存标记: ${actuallyHasContent}`);
        
        // 更新全局缓存和UI状态
        updateNovelCacheStatus(novel.id, actuallyHasContent);
      }
      
      // 如果没有内容但在线，尝试重新缓存
      if (!actuallyHasContent && navigator.onLine && !isOfflineMode) {
        try {
          console.log(`尝试从服务器重新缓存小说 "${novel.name}"...`);
          
          // 从API获取小说内容
          const novelData = await novelsApi.getNovel(novel.id);
          if (!novelData) {
            throw new Error('获取小说信息失败');
          }
          
          // 获取完整内容
          const content = await novelsApi.getFullNovelContent(novel.id);
          if (!content || !content.content) {
            throw new Error('获取小说内容失败');
          }
          
          // 缓存小说
          await novelOperations.cacheNovel(novelData, content.content);
          
          // 验证缓存是否成功
          const verifyCached = await novelOperations.isNovelCached(novel.id);
          if (!verifyCached) {
            throw new Error("缓存验证失败，请重试");
          }
          
          // 更新全局缓存和UI状态
          updateNovelCacheStatus(novel.id, true);
          
          console.log(`成功重新缓存小说 "${novel.name}"`);
          alert(`已成功重新缓存《${novel.name}》！现在可以离线阅读了。`);
        } catch (err) {
          console.error(`重新缓存小说失败:`, err);
          alert(`重新缓存《${novel.name}》失败: ${err.message}`);
        }
      } else if (actuallyHasContent) {
        alert(`小说《${novel.name}》的缓存状态已修复！`);
      } else {
        alert(`无法修复小说《${novel.name}》的缓存，请确保联网后重试。`);
      }
      
      // 刷新缓存统计
      refreshCacheStats();
    } catch (err) {
      console.error(`修复小说缓存失败:`, err);
      alert(`修复失败: ${err.message}`);
    } finally {
      setLoading(false);
    }
  };

  // 添加到小说操作菜单 - 解决循环引用问题
  const getNovelContextMenu = (novel) => {
    const menuItems = [
      { 
        icon: <FiBookOpen />, 
        label: '阅读',
        onClick: () => navigate(`/reader/${novel.id}`) 
      }
    ];
    
    if (navigator.onLine && !isOfflineMode) {
      menuItems.push({
        icon: novel.cached ? <FiCheck /> : <FiDownload />,
        label: novel.cached ? '已缓存' : '缓存本书',
        onClick: () => novel.cached ? null : handleCacheNovel(novel),
        disabled: novel.cached
      });
      
      // 添加修复/重新缓存选项
      menuItems.push({
        icon: <FiDownload />,
        label: '修复/重新缓存',
        onClick: () => fixSingleNovelCache(novel)
      });
    }
    
    return menuItems;
  };
  
  // 监听书架交互
  const bookClickHandler = (novel) => {
    navigate(`/reader/${novel.id}`);
  };
  
  // 长按/右键菜单
  const bookLongPressHandler = (novel, event) => {
    event.preventDefault();
    setContextMenu({
      show: true,
      x: event.clientX || event.touches[0].clientX,
      y: event.clientY || event.touches[0].clientY,
      novel,
      items: getNovelContextMenu(novel)
    });
  };
  
  // 辅助函数：更新小说缓存状态（全局缓存和UI）
  const updateNovelCacheStatus = (novelId, isCached) => {
    // 更新全局缓存
    if (globalCache.novels && globalCache.novels.length > 0) {
      globalCache.novels = globalCache.novels.map(n => 
        n.id === novelId ? { ...n, cached: isCached } : n
      );
    }
    
    // 更新当前状态中的小说
    setNovels(prev => prev.map(n => 
      n.id === novelId ? { ...n, cached: isCached } : n
    ));
    setFilteredNovels(prev => prev.map(n => 
      n.id === novelId ? { ...n, cached: isCached } : n
    ));
  };
  
  return (
    <ThemeProvider>
    <div className={`min-h-screen ${isDarkMode ? 'bg-gray-900 text-gray-100' : 'bg-gray-100 text-gray-900'} transition-colors duration-300`}>
      {/* 头部固定导航栏 */}
      <header className={`${isDarkMode ? 'bg-gray-800 border-gray-700' : 'bg-white border-gray-200'} shadow-sm border-b sticky top-0 z-10`}>
        <div className="container mx-auto px-3 py-3 flex items-center justify-between">
          <div className="flex items-center">
            <h1 className="text-base sm:text-xl font-bold">阅读器</h1>
            <div className="hidden md:flex space-x-4 ml-8">
              <button 
                className={`${isDarkMode ? 'text-gray-300 hover:text-white' : 'text-gray-600 hover:text-gray-900'} px-3 py-1.5 rounded-md hover:bg-opacity-10 ${showOnlyFavorites ? 'bg-yellow-100 bg-opacity-30 text-yellow-600 dark:text-yellow-400' : ''}`}
                onClick={() => {
                  // 切换收藏筛选
                  setShowOnlyFavorites(!showOnlyFavorites);
                  localStorage.setItem('bookshelf_showOnlyFavorites', !showOnlyFavorites);
                }}
              >
                <div className="flex items-center">
                  {showOnlyFavorites ? <FiStar className="mr-1.5" /> : <FiStar className="mr-1.5" />}
                  <span className="hidden sm:inline">收藏</span>
                </div>
              </button>
              
              <button
                className={`${isDarkMode ? 'text-gray-300 hover:text-white' : 'text-gray-600 hover:text-gray-900'} px-3 py-1.5 rounded-md hover:bg-opacity-10`}
                onClick={() => setShowReadingPopup(true)}
              >
                <div className="flex items-center">
                  <FiBookOpen className="mr-1.5" />
                  <span className="hidden sm:inline">最近阅读</span>
                </div>
              </button>
            </div>
          </div>
          
          <div className="flex items-center space-x-1 sm:space-x-3">
            {/* 主题切换按钮 */}
            <button 
              className={`p-2 rounded-full ${isDarkMode ? 'bg-gray-700 text-gray-300 hover:bg-gray-600' : 'bg-gray-200 text-gray-600 hover:bg-gray-300'}`}
              onClick={toggleTheme}
              aria-label="切换主题"
            >
              {isDarkMode ? <FiSun /> : <FiMoon />}
            </button>
              
            {/* 离线模式按钮 */}
            <button 
              className={`p-2 rounded-full ${isOfflineMode ? 'bg-yellow-500 text-white' : isDarkMode ? 'bg-gray-700 text-gray-300 hover:bg-gray-600' : 'bg-gray-200 text-gray-600 hover:bg-gray-300'}`}
              onClick={() => {
                toggleOfflineMode();
                // 离线模式变化后需要刷新列表状态已在toggleOfflineMode函数中处理，这里可以移除
              }}
              aria-label={isOfflineMode ? "本地书架模式" : "在线模式"}
              title={isOfflineMode ? "当前为本地书架模式，仅显示已缓存的小说" : "切换至本地书架模式"}
            >
              {isOfflineMode ? <FiWifiOff className="text-white" /> : <FiWifi />}
            </button>
            
            {/* 扫描按钮 */}
            <button 
              className={`p-2 rounded-full ${isScanningLoading ? 'bg-blue-100 text-blue-600 animate-pulse' : isDarkMode ? 'bg-gray-700 text-gray-300 hover:bg-gray-600' : 'bg-gray-200 text-gray-600 hover:bg-gray-300'}`}
              onClick={handleScan}
              disabled={isScanningLoading}
              aria-label="扫描新小说"
              title="扫描新小说"
            >
              {isScanningLoading ? <FiLoader className="animate-spin" /> : <FiRefreshCw />}
            </button>
          </div>
        </div>
      </header>
      
      <div className="container mx-auto px-0 md:px-4 pb-4 md:py-4 flex flex-col md:flex-row">
        {/* 侧边栏 - 在移动设备上可折叠 */}
        <div className={`
          md:w-64 bg-white border-r border-gray-200 flex-shrink-0 
          ${sidebarCollapsed ? 'hidden md:block' : 'fixed inset-0 z-20 w-64'}
          transition-all duration-300 ease-in-out max-h-full overflow-y-auto
        `}>
          {/* 移动设备关闭按钮 */}
          {!sidebarCollapsed && (
            <div className="flex justify-end p-2 md:hidden">
              <button 
                className="p-2 rounded-full text-gray-500 hover:bg-gray-100"
                onClick={() => setSidebarCollapsed(true)}
              >
                <FiX size={24} />
              </button>
            </div>
          )}
          
          {/* 侧边栏内容 */}
          <div className="p-4">
            {/* 筛选和设置 */}
            <div className="mb-6">
              <h3 className="font-medium text-gray-800 mb-3 flex items-center text-base sm:text-lg">
                <FiSettings className="mr-2 text-gray-500" /> 设置
              </h3>
              
              {/* 视图模式 */}
              <div className="mb-4">
                <div className="text-sm sm:text-base text-gray-700 mb-2">显示模式</div>
                <div className="flex space-x-2">
                  <button 
                    className={`flex-1 py-2 px-2 rounded-md transition-all duration-300 flex justify-center items-center text-sm sm:text-base ${viewMode === 'grid' 
                      ? 'bg-blue-500 text-white shadow-sm' 
                      : 'bg-gray-100 text-gray-700 hover:bg-gray-200'}`}
                    onClick={() => setViewMode('grid')}
                  >
                    <FiGrid className="mr-1" />
                    网格
                  </button>
                  <button 
                    className={`flex-1 py-2 px-2 rounded-md transition-all duration-300 flex justify-center items-center text-sm sm:text-base ${viewMode === 'list' 
                      ? 'bg-blue-500 text-white shadow-sm' 
                      : 'bg-gray-100 text-gray-700 hover:bg-gray-200'}`}
                    onClick={() => setViewMode('list')}
                  >
                    <FiList className="mr-1" />
                    列表
                  </button>
                </div>
              </div>
              
              {/* 每行显示数量 */}
              {viewMode === 'grid' && (
                <div className="mb-4">
                  <div className="flex items-center mb-2">
                    <FiColumns className="mr-1 text-gray-500" />
                    <div className="text-sm sm:text-base text-gray-700">每行显示数量</div>
                  </div>
                  <div className="flex flex-wrap gap-2">
                    {[2, 3, 4, 5, 6].map(cols => (
                      <button
                        key={cols}
                        className={`w-10 h-10 rounded-md flex items-center justify-center transition-all duration-300 text-sm sm:text-base ${
                          gridColumns === cols
                            ? 'bg-blue-500 text-white shadow-sm'
                            : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
                        }`}
                        onClick={() => setGridColumns(cols)}
                      >
                        {cols}
                      </button>
                    ))}
                  </div>
                </div>
              )}
              
              {/* 筛选条件 */}
              <div className="mb-4">
                <button 
                  className={`w-full py-2 px-2 rounded-md transition-all duration-300 flex justify-center items-center text-sm sm:text-base ${showOnlyFavorites 
                    ? 'bg-yellow-500 text-white shadow-sm' 
                    : 'bg-gray-100 text-gray-700 hover:bg-gray-200'}`}
                  onClick={() => setShowOnlyFavorites(!showOnlyFavorites)}
                >
                  <FiStar className="mr-1" />
                  {showOnlyFavorites ? '显示全部' : '仅显示收藏'}
                </button>
              </div>
            </div>
            
            {/* 排序方式 */}
            <div className="mb-6">
              <h3 className="font-medium text-gray-800 mb-3 text-base sm:text-lg">排序方式</h3>
              <select
                className="block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 transition-all duration-300 text-sm sm:text-base p-2"
                value={sortBy}
                onChange={(e) => setSortBy(e.target.value)}
              >
                <option value="lastRead">最近阅读</option>
                <option value="default">默认排序</option>
                <option value="name">按名称</option>
                <option value="wordCount-desc">字数 (多到少)</option>
                <option value="wordCount-asc">字数 (少到多)</option>
                <option value="size">文件大小</option>
              </select>
            </div>
            
            {/* 最近阅读 */}
            {recentReads.length > 0 && (
              <div className="mb-6">
                <h3 className="font-medium text-gray-800 mb-3 flex items-center text-base sm:text-lg">
                  <FiBookOpen className="mr-2 text-blue-500" /> 最近阅读
                </h3>
                <div className="space-y-2 max-h-60 overflow-y-auto pr-1 border rounded-md border-gray-200">
                  {recentReads.slice(0, 5).map(item => {
                    const novel = recentReadsNovels[item.novelId];
                    if (!novel) return null;
                    
                    return (
                      <div 
                        key={item.novelId}
                        className="p-2 hover:bg-gray-50 cursor-pointer border-b border-gray-100 last:border-b-0"
                        onClick={() => handleRead(novel, item)}
                      >
                        <div className="font-medium text-sm sm:text-base text-gray-800 truncate">{novel.name}</div>
                        <div className="flex items-center text-xs sm:text-sm text-gray-500 mt-1">
                          <FiClock className="mr-1" />
                          {formatDate(item.timestamp)}
                        </div>
                      </div>
                    );
                  })}
                  {recentReads.length > 5 && (
                    <div className="p-2 text-center">
                      <button 
                        className="text-blue-500 text-sm sm:text-base hover:text-blue-700"
                        onClick={() => setShowReadingPopup(true)}
                      >
                        查看全部
                      </button>
                    </div>
                  )}
                </div>
              </div>
            )}
            
            {/* 离线管理按钮 */}
            <div className="mt-6">
              <div className="font-semibold mb-2 text-gray-700 flex items-center">
                {!sidebarCollapsed && '离线阅读'}
                <button 
                  className={`p-2 rounded-full hover:bg-gray-100 ml-auto text-gray-700 ${isOfflineMode ? 'bg-yellow-100 text-yellow-700' : ''}`}
                  onClick={toggleOfflineMode}
                  title={isOfflineMode ? "关闭离线模式" : "开启离线模式"}
                >
                  <FiWifiOff />
                </button>
              </div>
              
              {!sidebarCollapsed && (
                <div className="text-sm text-gray-500 mb-2">
                  离线模式: <span className={`font-semibold ${isOfflineMode ? 'text-yellow-600' : 'text-green-600'}`}>
                    {isOfflineMode ? '已开启' : '已关闭'}
                  </span>
                </div>
              )}
              
              <button
                className="w-full flex items-center justify-center md:justify-start p-2 rounded hover:bg-gray-100 text-blue-600"
                onClick={() => setShowOfflineManager(true)}
              >
                <FiDownload className="mr-2" />
                {!sidebarCollapsed && '管理离线数据'}
              </button>
            </div>
          </div>
        </div>
        
        {/* 侧边栏折叠按钮 - 仅桌面显示 */}
        <div className={`hidden md:block absolute left-64 top-4 z-10 ${sidebarCollapsed ? 'left-0' : ''}`}>
          <button 
            className="p-1 bg-white border border-gray-200 rounded-full shadow-sm text-gray-500 hover:text-gray-700"
            onClick={() => setSidebarCollapsed(!sidebarCollapsed)}
          >
            {sidebarCollapsed ? <FiChevronRight size={18} /> : <FiChevronLeft size={18} />}
          </button>
        </div>
        
        {/* 侧边栏背景遮罩 - 移动设备 */}
        {!sidebarCollapsed && (
          <div 
            className="fixed inset-0 bg-black bg-opacity-50 z-10 md:hidden"
            onClick={() => setSidebarCollapsed(true)}
          ></div>
        )}
        
        {/* 主内容区 - 添加渐入动画 */}
        <div className={`flex-1 flex flex-col overflow-hidden ${sidebarCollapsed ? '' : 'md:ml-64'} transition-all duration-300 ${fadeIn ? 'opacity-100' : 'opacity-0'} transition-opacity duration-300`}>
          {/* 搜索栏 */}
          <div className="p-3 sm:p-4 bg-white shadow-sm z-10 border-b dark:bg-gray-800 dark:border-gray-700 flex-shrink-0">
            <div className="relative" ref={searchInputRef}>
              <input
                type="text"
                className="pl-10 pr-10 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 transition-all duration-300 text-base py-2.5"
                placeholder="搜索小说...  (按 / 聚焦)"
                value={searchTerm}
                onChange={(e) => setSearchTerm(e.target.value)}
                onKeyDown={(e) => {
                  if (e.key === 'Enter') {
                    handleSearch(searchTerm);
                  }
                }}
                onFocus={() => {
                  if (searchTerm.trim() || searchHistory.length > 0) {
                    setShowSearchSuggestions(true);
                  }
                }}
              />
              <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
                <FiSearch className="h-5 w-5 text-gray-400" />
              </div>
              <div className="absolute inset-y-0 right-0 pr-3 flex items-center">
                {searchTerm && (
                  <button 
                    className="text-gray-400 hover:text-gray-600"
                    onClick={() => setSearchTerm('')}
                  >
                    <FiX className="h-5 w-5" />
                  </button>
                )}
              </div>
              
              {/* 搜索建议和历史 */}
              {showSearchSuggestions && (
                <div className="absolute w-full bg-white mt-1 border border-gray-200 rounded-md shadow-lg z-10">
                  {searchSuggestions.length > 0 ? (
                    <div>
                      <div className="px-3 py-2 border-b border-gray-100 text-xs sm:text-sm text-gray-500 flex items-center">
                        <FiSearch className="mr-1" /> 搜索建议
                      </div>
                      <ul>
                        {searchSuggestions.map((suggestion, idx) => (
                          <li key={`suggestion-${idx}`}>
                            <button
                              className="w-full text-left px-4 py-2 hover:bg-gray-50 text-sm sm:text-base flex items-center"
                              onClick={() => handleSearch(suggestion)}
                            >
                              <FiCornerDownLeft className="mr-2 text-gray-400" />
                              {suggestion}
                            </button>
                          </li>
                        ))}
                      </ul>
                    </div>
                  ) : searchHistory.length > 0 ? (
                    <div>
                      <div className="px-3 py-2 border-b border-gray-100 text-xs sm:text-sm text-gray-500 flex justify-between items-center">
                        <span className="flex items-center">
                          <FiClock className="mr-1" /> 搜索历史
                        </span>
                        <button 
                          className="text-xs sm:text-sm text-red-500 hover:text-red-700"
                          onClick={clearSearchHistory}
                        >
                          清除历史
                        </button>
                      </div>
                      <ul>
                        {searchHistory.slice(0, 5).map((term, idx) => (
                          <li key={`history-${idx}`}>
                            <button
                              className="w-full text-left px-4 py-2 hover:bg-gray-50 text-sm sm:text-base flex items-center"
                              onClick={() => handleSearch(term)}
                            >
                              <FiClock className="mr-2 text-gray-400" />
                              {term}
                            </button>
                          </li>
                        ))}
                      </ul>
                    </div>
                  ) : null}
                </div>
              )}
            </div>
          </div>
          
          {/* 移动端快速网格设置栏 - 仅在网格模式和侧边栏折叠时显示 */}
          {viewMode === 'grid' && sidebarCollapsed && (
            <div className="sm:hidden bg-white dark:bg-gray-800 px-3 py-2 flex items-center justify-between shadow-sm">
              <div className="flex items-center">
                <FiColumns className="mr-2 text-gray-500 dark:text-gray-400" />
                <span className="text-sm text-gray-700 dark:text-gray-300">每行显示</span>
              </div>
              <div className="flex space-x-1">
                {[2, 3, 4].map(cols => (
                  <button
                    key={cols}
                    className={`w-8 h-8 rounded-md flex items-center justify-center text-sm
                      ${gridColumns === cols
                        ? 'bg-blue-500 text-white shadow-sm'
                        : 'bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600'
                      }`}
                    onClick={() => setGridColumns(cols)}
                  >
                    {cols}
                  </button>
                ))}
              </div>
            </div>
          )}
          
          {/* 小说列表区域 - 使用flex-1填充剩余空间，允许内容区滚动 */}
          <div className="flex-1 overflow-y-auto p-3 sm:p-4">
            {/* 小说列表 */}
            {loading ? (
              <div className="flex justify-center items-center my-12">
                <div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-blue-500"></div>
                <p className="ml-3 text-gray-600 text-base sm:text-lg">加载中...</p>
              </div>
            ) : isFiltering ? (
              <div className="flex justify-center items-center my-12">
                <div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-blue-500"></div>
                <p className="ml-3 text-gray-600 text-base sm:text-lg">正在筛选...</p>
              </div>
            ) : filteredNovels.length === 0 ? (
              <div className="text-center my-12 p-8 bg-white rounded-xl shadow-sm border border-gray-200">
                <svg xmlns="http://www.w3.org/2000/svg" className="h-16 w-16 mx-auto text-gray-300 mb-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1} d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
                </svg>
                <p className="text-gray-600 text-base sm:text-lg">没有找到匹配的小说</p>
              </div>
            ) : viewMode === 'grid' ? (
              // 在此处应用修改后的网格样式类
              <div className={`grid ${getGridColumnsClass(gridColumns)} gap-1.5 sm:gap-4`}>
                {currentPageData.map((novel, index) => renderNovelCard(novel, index))}
              </div>
            ) : (
              // 列表视图保持不变
              <div className="bg-white rounded-xl shadow-sm overflow-hidden border border-gray-200">
                <div className="overflow-x-auto">
                  <table className="min-w-full divide-y divide-gray-200">
                    <thead className="bg-gray-50">
                      <tr>
                        <th scope="col" className="px-3 sm:px-6 py-3 text-left text-xs sm:text-sm font-medium text-gray-500 uppercase tracking-wider">
                          名称
                        </th>
                        <th scope="col" className="px-3 sm:px-6 py-3 text-left text-xs sm:text-sm font-medium text-gray-500 uppercase tracking-wider">
                          字数
                        </th>
                        <th scope="col" className="px-3 sm:px-6 py-3 text-left text-xs sm:text-sm font-medium text-gray-500 uppercase tracking-wider">
                          大小
                        </th>
                        <th scope="col" className="px-3 sm:px-6 py-3 text-left text-xs sm:text-sm font-medium text-gray-500 uppercase tracking-wider">
                          阅读状态
                        </th>
                        <th scope="col" className="px-3 sm:px-6 py-3 text-left text-xs sm:text-sm font-medium text-gray-500 uppercase tracking-wider">
                          操作
                        </th>
                      </tr>
                    </thead>
                    <tbody className="bg-white divide-y divide-gray-200">
                      {currentPageData.map(novel => (
                        <NovelRow 
                          key={novel.id}
                          novel={novel}
                          isFavorite={favorites.includes(novel.id)}
                          readingProgress={getReadingProgress(novel.id)}
                          onToggleFavorite={handleToggleFavorite}
                          onRead={handleRead}
                        />
                      ))}
                    </tbody>
                  </table>
                </div>
              </div>
            )}
            
            {/* 分页控制 - 传统分页控件 */}
            {totalPages > 1 && (
              <div className="flex justify-center items-center flex-wrap gap-2 mt-6 mb-4 px-2">
                <button
                  className="px-2 sm:px-3 py-1.5 sm:py-2 rounded-md bg-white border border-gray-300 text-gray-700 disabled:opacity-50 disabled:cursor-not-allowed shadow-sm hover:bg-gray-50 transition-colors duration-300 text-sm sm:text-base"
                  onClick={() => setCurrentPage(prev => Math.max(prev - 1, 1))}
                  disabled={currentPage === 1}
                >
                  上一页
                </button>
                
                <div className="flex items-center space-x-1 sm:space-x-2 overflow-x-auto max-w-[180px] sm:max-w-none py-1">
                  {pageNumbers.map((item, index) => {
                    if (item.type === 'ellipsis') {
                      return (
                        <span key={`ellipsis-${index}`} className="px-1 sm:px-2 text-gray-500">
                          ...
                        </span>
                      );
                    }
                    
                    return (
                      <button
                        key={item.number}
                        className={`min-w-[32px] h-8 sm:h-10 px-1.5 sm:px-3 py-1 sm:py-2 rounded-md transition-all duration-300 text-sm sm:text-base ${
                          currentPage === item.number 
                            ? 'bg-blue-500 text-white font-medium shadow-sm' 
                            : 'bg-white border border-gray-300 text-gray-700 hover:bg-gray-50'
                        }`}
                        onClick={() => setCurrentPage(item.number)}
                      >
                        {item.number}
                      </button>
                    );
                  })}
                </div>
                
                <button
                  className="px-2 sm:px-3 py-1.5 sm:py-2 rounded-md bg-white border border-gray-300 text-gray-700 disabled:opacity-50 disabled:cursor-not-allowed shadow-sm hover:bg-gray-50 transition-colors duration-300 text-sm sm:text-base"
                  onClick={() => setCurrentPage(prev => Math.min(prev + 1, totalPages))}
                  disabled={currentPage === totalPages}
                >
                  下一页
                </button>
                
                {/* 添加快速跳转到首页和末页的按钮，在移动设备上显示 */}
                <div className="flex items-center space-x-1 sm:hidden ml-1">
                  {currentPage > 2 && (
                    <button
                      className="min-w-[32px] h-8 px-1.5 py-1 rounded-md bg-white border border-gray-300 text-gray-700 flex items-center justify-center"
                      onClick={() => setCurrentPage(1)}
                    >
                      <span className="text-xs">首页</span>
                    </button>
                  )}
                  {currentPage < totalPages - 1 && (
                    <button
                      className="min-w-[32px] h-8 px-1.5 py-1 rounded-md bg-white border border-gray-300 text-gray-700 flex items-center justify-center"
                      onClick={() => setCurrentPage(totalPages)}
                    >
                      <span className="text-xs">末页</span>
                    </button>
                  )}
                </div>
              </div>
            )}
          </div>
        </div>
      </div>
      
      {/* 离线数据管理对话框 */}
      {showOfflineManager && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
          <div className="bg-white rounded-lg shadow-xl w-full max-w-2xl max-h-[80vh] overflow-auto">
            <div className="p-4 border-b flex justify-between items-center">
              <h2 className="text-xl font-semibold">离线数据管理</h2>
              <button 
                className="p-2 rounded-full hover:bg-gray-100"
                onClick={() => setShowOfflineManager(false)}
              >
                <FiX />
              </button>
            </div>
            
            <div className="p-4">
              {/* 离线模式开关 */}
              <div className="mb-6 p-4 bg-gray-50 rounded-md">
                <div className="flex items-center justify-between mb-2">
                  <span className="font-semibold">离线模式</span>
                  <button
                    className={`px-3 py-1 rounded text-white ${isOfflineMode ? 'bg-yellow-500' : 'bg-green-500'}`}
                    onClick={toggleOfflineMode}
                  >
                    {isOfflineMode ? '已开启' : '已关闭'}
                  </button>
                </div>
                <p className="text-sm text-gray-600">
                  {isOfflineMode ? 
                    '离线模式已开启，应用将仅使用已缓存的内容，不会尝试从网络加载数据。' : 
                    '离线模式已关闭，应用将优先使用缓存内容，必要时从网络加载数据。'}
                </p>
              </div>
              
              {/* 缓存状态修复按钮 */}
              <div className="mb-6 p-4 bg-gray-50 rounded-md">
                <div className="flex items-center justify-between mb-2">
                  <span className="font-semibold">缓存状态检查</span>
                  <div className="flex space-x-2">
                    <button
                      className="px-3 py-1 rounded text-white bg-blue-500 hover:bg-blue-600"
                      onClick={validateCacheStatus}
                      disabled={loading}
                    >
                      {loading ? '检查中...' : '快速检查'}
                    </button>
                    <button
                      className="px-3 py-1 rounded text-white bg-green-500 hover:bg-green-600"
                      onClick={repairAllCacheStatus}
                      disabled={loading}
                    >
                      {loading ? '修复中...' : '深度修复'}
                    </button>
                  </div>
                </div>
                <p className="text-sm text-gray-600">
                  如果您遇到离线模式下无法阅读已缓存小说的问题，请使用此功能检查并修复缓存状态。深度修复可解决更复杂的问题。
                </p>
              </div>
              
              {/* 手动缓存小说 */}
              <div className="mb-6 p-4 bg-blue-50 rounded-md">
                <h3 className="font-semibold mb-2">手动缓存小说</h3>
                <div className="flex items-center">
                  <div className="flex-1 mr-2">
                    <select 
                      className="w-full p-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500"
                      id="manualCacheSelect"
                      defaultValue=""
                    >
                      <option value="" disabled>选择要缓存的小说</option>
                      {novels.filter(n => !n.cached).map(novel => (
                        <option key={novel.id} value={novel.id}>
                          {novel.name} ({formatWordCount(novel.size)})
                        </option>
                      ))}
                    </select>
                  </div>
                  <button 
                    className="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 flex-shrink-0 flex items-center"
                    onClick={() => {
                      const select = document.getElementById('manualCacheSelect');
                      const id = select?.value;
                      if (id) {
                        const novelToCache = novels.find(n => n.id == id);
                        if (novelToCache) {
                          // 关闭对话框，避免界面冲突
                          setShowOfflineManager(false);
                          // 延迟一点执行缓存操作，让对话框先关闭
                          setTimeout(() => {
                            handleCacheNovel(novelToCache);
                          }, 100);
                        }
                      } else {
                        alert('请先选择要缓存的小说');
                      }
                    }}
                  >
                    <FiDownload className="mr-2" />
                    开始缓存
                  </button>
                </div>
                <p className="text-xs text-gray-500 mt-2">
                  已缓存的小说不会显示在列表中。缓存小说可能需要较长时间，请耐心等待。
                </p>
              </div>
              
              {/* 缓存统计 */}
              <div className="mb-6">
                <h3 className="font-semibold mb-2">缓存统计</h3>
                {!cacheStats ? (
                  <p className="text-gray-500">加载统计信息中...</p>
                ) : cacheStats.error ? (
                  <p className="text-red-500">获取统计信息失败: {cacheStats.error}</p>
                ) : (
                  <div className="grid grid-cols-2 gap-4">
                    <div className="bg-blue-50 p-3 rounded-md">
                      <div className="text-xs text-gray-500">已缓存小说</div>
                      <div className="text-xl font-semibold">{cacheStats.cachedNovels || 0}</div>
                    </div>
                    <div className="bg-green-50 p-3 rounded-md">
                      <div className="text-xs text-gray-500">占用空间</div>
                      <div className="text-xl font-semibold">{cacheStats.sizeMB || '0'} MB</div>
                    </div>
                  </div>
                )}
                
                {/* 刷新按钮 */}
                <div className="mt-2 flex justify-end">
                  <button
                    className="text-xs text-blue-500 flex items-center"
                    onClick={refreshCacheStats}
                  >
                    刷新统计
                  </button>
                </div>
              </div>
              
              {/* 批量操作 */}
              <div className="mb-6">
                <h3 className="font-semibold mb-2">批量操作</h3>
                <div className="flex space-x-2">
                  <button
                    className="px-4 py-2 bg-blue-500 text-white rounded flex items-center"
                    onClick={() => {
                      setShowOfflineManager(false);
                      // 选择所有未缓存的小说
                      const uncachedNovels = novels
                        .filter(novel => !novel.cached)
                        .map(novel => novel.id);
                      setSelectedNovels(uncachedNovels);
                    }}
                  >
                    <FiDownload className="mr-2" />
                    下载所有小说
                  </button>
                  <button
                    className="px-4 py-2 bg-red-100 text-red-600 rounded flex items-center"
                    onClick={clearAllCache}
                  >
                    <FiTrash2 className="mr-2" />
                    清除所有缓存
                  </button>
                </div>
              </div>
              
              {/* 缓存使用提示 */}
              <div className="mt-4 text-sm text-gray-500 bg-yellow-50 p-3 rounded-md">
                <p className="mb-2 font-semibold flex items-center">
                  <FiClock className="mr-2" />
                  提示
                </p>
                <ul className="list-disc list-inside space-y-1">
                  <li>缓存小说可以在没有网络连接的情况下阅读</li>
                  <li>已缓存的小说在书架中显示下载图标</li>
                  <li>离线模式下只能阅读已缓存的小说</li>
                  <li>清除缓存可以释放存储空间，但需要再次联网才能阅读</li>
                </ul>
              </div>
            </div>
            
            <div className="p-4 border-t flex justify-end">
              <button
                className="px-4 py-2 bg-gray-200 rounded"
                onClick={() => setShowOfflineManager(false)}
              >
                关闭
              </button>
            </div>
          </div>
        </div>
      )}
      
      {/* 在离线阅读区块下方添加数据库管理区块 */}
      {/* 数据管理区块已移除 */}
    </div>
    </ThemeProvider>
  );
}

// 导出包装了主题提供者的组件
export default function BookshelfWithTheme() {
  return (
    <ThemeProvider>
      <Bookshelf />
    </ThemeProvider>
  );
} 